from .bst import BST, AVLTree
from .linkedlist import LinkedList


class BSTSet:
    def __init__(self):
        self.tree = BST()

    def __len__(self):
        return len(self.tree)

    def is_empty(self):
        return self.tree.is_empty()

    def add(self, item):
        self.tree.add(item)

    def __contains__(self, item):
        return item in self.tree

    def remove(self, item):
        return self.remove(item)

    @classmethod
    def generate(cls, arr):
        try:
            iter(arr)
        except TypeError:
            raise TypeError("'arr' object is not iterable.")
        b = cls()
        for i in arr:
            b.add(i)
        return b


class AVLSet:
    def __init__(self):
        self.tree = AVLTree()

    def __len__(self):
        return len(self.tree)

    def is_empty(self):
        return self.tree.is_empty()

    def add(self, item):
        self.tree.add(item, None)

    def __contains__(self, item):
        return item in self.tree

    def remove(self, item):
        return self.remove(item)

    @classmethod
    def generate(cls, arr):
        try:
            iter(arr)
        except TypeError:
            raise TypeError("'arr' object is not iterable.")
        b = cls()
        for i in arr:
            b.add(i)
        return b


class LinkedListSet:
    def __init__(self):
        self.linked_list = LinkedList()

    def get_size(self):
        return self.linked_list.get_size()

    def is_empty(self):
        return self.linked_list.is_empty()

    def contains(self, element):
        """O(n)"""
        return self.linked_list.contains(element)

    def add(self, element):
        """O(n)"""
        if not self.linked_list.contains(element):
            self.linked_list.add_first(element)

    def remove(self, element):
        """O(n)"""
        self.linked_list.remove_element(element)

    @classmethod
    def generate(cls, arr):
        try:
            iter(arr)
        except TypeError:
            raise TypeError("'arr' object is not iterable.")
        lls = cls()
        for i in arr:
            lls.add(i)
        return lls
